home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / Utilities / AltPoint.cpp next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  11.5 KB  |  526 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        AltPoint.cpp
  3.  
  4.     Contains:    Alternate ODPoint, ODRect (C++ savvy)
  5.  
  6.     Owned by:    Jens Alfke
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <3>     9/17/96    RA        1278220: AltPoint.cpp includes ODDebug.h
  13.                                     twice
  14.          <2>     5/24/96    jpa        1.1MRD: Inlined copy ctor and oper=
  15.  
  16.     In Progress:
  17.         
  18. */
  19.  
  20. #ifndef _ALTPOINT_
  21. #include "AltPoint.h"
  22. #endif
  23.  
  24. #ifndef SOM_Module_OpenDoc_Global_Types_defined
  25. #include "ODTypesM.xh"
  26. #endif
  27.  
  28. #ifndef _EXCEPT_
  29. #include "Except.h"
  30. #endif
  31.  
  32. #ifndef _ODDEBUG_
  33. #include "ODDebug.h"
  34. #endif
  35.  
  36. #ifndef _LINEOPS_
  37. #include "LineOps.h"        /* For kFixedEpsilon */
  38. #endif
  39.  
  40. #include <string.h>
  41.  
  42.  
  43. #ifdef _PLATFORM_MACINTOSH_
  44.     #ifndef __GXMATH__
  45.     #include <GXMath.h>
  46.     #endif
  47. #endif
  48.  
  49. #pragma segment ODShape
  50.  
  51.  
  52. //==============================================================================
  53. // ODPoint
  54. //==============================================================================
  55.  
  56.  
  57. #ifdef _PLATFORM_MACINTOSH_
  58. ODPoint::ODPoint( Point qdpt )
  59. {
  60.     x = IntToFixed(qdpt.h);
  61.     y = IntToFixed(qdpt.v);
  62. }
  63. #endif
  64.  
  65.  
  66. #ifdef _PLATFORM_MACINTOSH_
  67. ODPoint& ODPoint::operator= ( const Point &pt )
  68. {
  69.     x = IntToFixed(pt.h);
  70.     y = IntToFixed(pt.v);
  71.     return *this;
  72. }
  73. #endif
  74.  
  75.  
  76. void ODPoint::Offset ( ODCoordinate xx, ODCoordinate yy )
  77. {
  78.     x += xx;
  79.     y += yy;
  80. }
  81.  
  82.  
  83. void ODPoint::operator+= ( const ODPoint &pt )
  84. {
  85.     x += pt.x;
  86.     y += pt.y;
  87. }
  88.  
  89.  
  90. void ODPoint::operator-= ( const ODPoint &pt )
  91. {
  92.     x -= pt.x;
  93.     y -= pt.y;
  94. }
  95.  
  96.  
  97. #ifdef _PLATFORM_MACINTOSH_
  98. void ODPoint::operator+= ( const Point &pt )
  99. {
  100.     x += IntToFixed(pt.h);
  101.     y += IntToFixed(pt.v);
  102. }
  103.  
  104.  
  105. void ODPoint::operator-= ( const Point &pt )
  106. {
  107.     x -= IntToFixed(pt.h);
  108.     y -= IntToFixed(pt.v);
  109. }
  110.  
  111. Point
  112. ODPoint::AsQDPoint( ) const
  113. {
  114.     Point pt;
  115.     pt.h = FixedToInt(x);
  116.     pt.v = FixedToInt(y);
  117.     return pt;
  118. }
  119. #endif
  120.  
  121.  
  122. ODSShort
  123. ODPoint::IntX( ) const
  124. {
  125.     return FixedToInt(x);
  126. }
  127.  
  128.  
  129. ODSShort
  130. ODPoint::IntY( ) const
  131. {
  132.     return FixedToInt(y);
  133. }
  134.  
  135.  
  136. ODBoolean
  137. ODPoint::operator==( const ODPoint &pt ) const
  138. {
  139.     return x==pt.x && y==pt.y;
  140. }
  141.  
  142.  
  143. ODBoolean
  144. ODPoint::operator!=( const ODPoint &pt ) const
  145. {
  146.     return x!=pt.x || y!=pt.y;
  147. }
  148.  
  149.  
  150. ODBoolean
  151. ODPoint::ApproxEquals( const ODPoint& pt ) const
  152. {
  153.     ODFixed delta;
  154.     delta = x-pt.x;
  155.     if( delta>kFixedEpsilon || delta<-kFixedEpsilon )
  156.         return kODFalse;
  157.     delta = y-pt.y;
  158.     if( delta>kFixedEpsilon || delta<-kFixedEpsilon )
  159.         return kODFalse;
  160.     return kODTrue;
  161. }
  162.  
  163.  
  164. //==============================================================================
  165. // ODRect
  166. //==============================================================================
  167.  
  168.  
  169. #pragma segment ODShape
  170.  
  171.  
  172. #define ASSERTVALID()        WASSERT(right>=left && bottom>=top)
  173.  
  174.  
  175. //------------------------------------------------------------------------------
  176. // ::ODRect( corner1, corner2 )
  177. //
  178. // Construct a rectangle given two opposite corners (not necessarily topLeft,botRight)
  179. //------------------------------------------------------------------------------
  180.  
  181. ODRect::ODRect( const ODPoint &a, const ODPoint &b )
  182. {
  183.     this->Set(a,b);
  184. }
  185.  
  186.  
  187. //------------------------------------------------------------------------------
  188. // ::ODRect( topLeft, width, height )
  189. //
  190. // Construct a rectangle given its origin, width and height.
  191. //------------------------------------------------------------------------------
  192.  
  193. ODRect::ODRect( const ODPoint &topLeft, ODCoordinate width, ODCoordinate height )
  194. {
  195.     WASSERT(width>=0);
  196.     WASSERT(height>=0);
  197.     
  198.     left = topLeft.x;        right = topLeft.x + width;
  199.     top  = topLeft.y;        bottom= topLeft.y + height;
  200. }
  201.  
  202.  
  203. #ifdef _PLATFORM_MACINTOSH_
  204. //------------------------------------------------------------------------------
  205. // ::ODRect( Rect )
  206. //
  207. // Construct an ODRect from a QuickDraw Rect
  208. //------------------------------------------------------------------------------
  209.  
  210. ODRect::ODRect( const Rect &r )
  211. {
  212.     left = ff(r.left);        right = ff(r.right);
  213.     top  = ff(r.top);        bottom= ff(r.bottom);
  214. }
  215.  
  216.  
  217. //------------------------------------------------------------------------------
  218. // ::= Rect
  219. //
  220. // Set an ODRect from a QuickDraw Rect
  221. //------------------------------------------------------------------------------
  222.  
  223. ODRect&
  224. ODRect:: operator= ( const Rect &r )
  225. {
  226.     left = ff(r.left);        right = ff(r.right);
  227.     top  = ff(r.top);        bottom= ff(r.bottom);
  228.     ASSERTVALID();
  229.     return *this;
  230. }
  231. #endif
  232.  
  233.  
  234. //------------------------------------------------------------------------------
  235. // ::Set
  236. //
  237. // Set all four coordinates of a rectangle. Warn if the resulting rect is bogus.
  238. //------------------------------------------------------------------------------
  239.  
  240. void
  241. ODRect::Set( ODCoordinate l, ODCoordinate t, ODCoordinate r, ODCoordinate b )
  242. {
  243.     left = l;                right = r;
  244.     top  = t;                bottom= b;
  245.     ASSERTVALID();
  246. }
  247.  
  248.  
  249. //------------------------------------------------------------------------------
  250. // ::Set
  251. //
  252. // Set all four coordinates of a rectangle. Warn if the resulting rect is bogus.
  253. //------------------------------------------------------------------------------
  254.  
  255. void
  256. ODRect::Set( const ODPoint &origin, ODCoordinate width, ODCoordinate height )
  257. {
  258.     WASSERT(width>=0);
  259.     WASSERT(height>=0);
  260.     left = origin.x;                right = left+width;
  261.     top  = origin.y;                bottom= top +height;
  262. }
  263.  
  264.  
  265. //------------------------------------------------------------------------------
  266. // ::Set
  267. //
  268. // Construct a rectangle given two opposite corners (not necessarily topLeft,botRight)
  269. //------------------------------------------------------------------------------
  270.  
  271. void
  272. ODRect::Set( const ODPoint &a, const ODPoint &b )
  273. {
  274.     if( a.x<b.x ) {
  275.         left = a.x;
  276.         right= b.x;
  277.     } else {
  278.         left = b.x;
  279.         right= a.x;
  280.     }
  281.     if( a.y<b.y ) {
  282.         top   = a.y;
  283.         bottom= b.y;
  284.     } else {
  285.         top   = b.y;
  286.         bottom= a.y;
  287.     }
  288. }
  289.  
  290.  
  291. //------------------------------------------------------------------------------
  292. // ::SetInt
  293. //
  294. // Set coordinates of a rectangle from integers. Warn if the resulting rect is bogus.
  295. //------------------------------------------------------------------------------
  296.  
  297. void
  298. ODRect::SetInt( short l, short t, short r, short b )
  299. {
  300.     left = ff(l);            right = ff(r);
  301.     top  = ff(t);            bottom= ff(b);
  302.     ASSERTVALID();
  303. }
  304.  
  305.  
  306. //------------------------------------------------------------------------------
  307. // ::Offset
  308. //
  309. // Move a rectangle.
  310. //------------------------------------------------------------------------------
  311.  
  312. void
  313. ODRect::Offset( ODCoordinate x, ODCoordinate y )
  314. {
  315.     left += x;                right += x;
  316.     top  += y;                bottom+= y;
  317. }
  318.  
  319. void
  320. ODRect::Offset( const ODPoint &pt )
  321. {
  322.     left += pt.x;            right += pt.x;
  323.     top  += pt.y;            bottom+= pt.y;
  324. }
  325.  
  326.  
  327. //------------------------------------------------------------------------------
  328. // ::Inset
  329. //
  330. // Inset the edges of a rectangle, without collapsing to negative dimensions.
  331. //------------------------------------------------------------------------------
  332.  
  333. void
  334. ODRect::Inset( ODCoordinate x, ODCoordinate y )
  335. {
  336.     left += x;
  337.     right = Max(left,right-x);
  338.     top += y;
  339.     bottom = Max(top,bottom-y);
  340. }
  341.  
  342.  
  343. //------------------------------------------------------------------------------
  344. // ::Clear
  345. //
  346. // Zero all coordinates
  347. //------------------------------------------------------------------------------
  348.  
  349. void
  350. ODRect::Clear( )
  351. {
  352.     left = right = top = bottom = 0;
  353. }
  354.  
  355.  
  356. //------------------------------------------------------------------------------
  357. // :: &=
  358. //
  359. // Intersect me with another rectangle (result stored in me)
  360. //------------------------------------------------------------------------------
  361.  
  362. void
  363. ODRect:: operator&= ( const ODRect &r )
  364. {
  365.     left = Max(left,r.left);    right = Min(right, r.right);
  366.     top  = Max(top, r.top);        bottom= Min(bottom,r.bottom);
  367.     if( this->IsEmpty() )
  368.         this->Clear();
  369. }
  370.  
  371.  
  372. //------------------------------------------------------------------------------
  373. // :: |=
  374. //
  375. // Union me with another rectangle (result stored in me)
  376. //------------------------------------------------------------------------------
  377.  
  378. void
  379. ODRect:: operator|= ( const ODRect &r )
  380. {
  381.     if( this->IsEmpty() )
  382.         *this = r;
  383.     else if( !r.IsEmpty() ) {
  384.         left = Min(left,r.left);
  385.         right= Max(right,r.right);
  386.         top  = Min(top,r.top);
  387.         bottom=Max(bottom,r.bottom);
  388.     }
  389. }
  390.  
  391.  
  392. //------------------------------------------------------------------------------
  393. // :: |= ODPoint
  394. //
  395. // Union me with a point (expand to fit point)
  396. //------------------------------------------------------------------------------
  397.  
  398. void
  399. ODRect:: operator|= ( const ODPoint &pt )
  400. {
  401.     left = Min(left,pt.x);
  402.     right= Max(right,pt.x);
  403.     top  = Min(top,pt.y);
  404.     bottom=Max(bottom,pt.y);
  405. }
  406.  
  407.  
  408. #ifdef _PLATFORM_MACINTOSH_
  409. //------------------------------------------------------------------------------
  410. // :: AsQDRect
  411. //
  412. // Turn me into a QuickDraw rect
  413. //------------------------------------------------------------------------------
  414.  
  415. void
  416. ODRect::AsQDRect( Rect &r ) const
  417. {
  418.     SetRect(&r, FixedToInt(left), FixedToInt(top), FixedToInt(right), FixedToInt(bottom));
  419. }
  420. #endif
  421.  
  422.  
  423. //------------------------------------------------------------------------------
  424. // :: IsEmpty
  425. //
  426. // Do I have no area?
  427. //------------------------------------------------------------------------------
  428.  
  429. Boolean
  430. ODRect::IsEmpty( ) const
  431. {
  432.     return right<=left || bottom<=top;
  433. }
  434.  
  435.  
  436. //------------------------------------------------------------------------------
  437. // :: Contains( Point )
  438. //
  439. // Do I contain a point? (Remember, I don't contain my right and bottom edges.)
  440. //------------------------------------------------------------------------------
  441.  
  442. Boolean
  443. ODRect::Contains( const ODPoint &pt ) const
  444. {
  445.     return left<=pt.x && pt.x<right
  446.         && top <=pt.y && pt.y<bottom;
  447. }
  448.  
  449.  
  450. //------------------------------------------------------------------------------
  451. // :: Contains( Rect )
  452. //
  453. // Do I contain an entire rect?
  454. //------------------------------------------------------------------------------
  455.  
  456. Boolean
  457. ODRect::Contains( const ODRect &r ) const
  458. {
  459.     if( r.right<=r.left || r.bottom<=r.top )
  460.         return kODTrue;                    // Empty rect contained in anything
  461.     else
  462.         return left<=r.left && r.right<=right
  463.             && top <=r.top  && r.bottom<=bottom;
  464. }
  465.  
  466.  
  467. //------------------------------------------------------------------------------
  468. // :: ApproxContains( Rect )
  469. //
  470. // Do I approximately (within epsilon) contain an entire rect?
  471. //------------------------------------------------------------------------------
  472.  
  473. Boolean
  474. ODRect::ApproxContains( const ODRect &r ) const
  475. {
  476.     if( r.right<=r.left || r.bottom<=r.top )
  477.         return kODTrue;                    // Empty rect contained in anything
  478.     else
  479.         return left-kFixedEpsilon<=r.left && r.right<=right+kFixedEpsilon
  480.             && top-kFixedEpsilon <=r.top  && r.bottom<=bottom+kFixedEpsilon;
  481. }
  482.  
  483.  
  484. //------------------------------------------------------------------------------
  485. // :: ==
  486. //
  487. // Am I equal to another rect?
  488. //------------------------------------------------------------------------------
  489.  
  490. Boolean
  491. ODRect::operator==( const ODRect &r ) const
  492. {
  493.     return memcmp(this,&r,sizeof(ODRect)) == 0;
  494. }
  495.  
  496.  
  497. //------------------------------------------------------------------------------
  498. // :: ApproxEquals
  499. //
  500. // Am I approximately equal (within epsilon) to another rect?
  501. //------------------------------------------------------------------------------
  502.  
  503. ODBoolean
  504. ODRect::ApproxEquals( const ODRect &r ) const
  505. {
  506.     return left-r.left<=kFixedEpsilon     && left-r.left>=-kFixedEpsilon
  507.         && right-r.right<=kFixedEpsilon   && right-r.right>=-kFixedEpsilon
  508.         && top-r.top<=kFixedEpsilon       && top-r.top>=-kFixedEpsilon
  509.         && bottom-r.bottom<=kFixedEpsilon && bottom-r.bottom>=-kFixedEpsilon;
  510. }
  511.  
  512.  
  513. //------------------------------------------------------------------------------
  514. // :: Intersects
  515. //
  516. // Do I intersect another rectangle?
  517. // (Remember, I don't contain my right and bottom edges.)
  518. //------------------------------------------------------------------------------
  519.  
  520. Boolean
  521. ODRect::Intersects( const ODRect &r ) const
  522. {
  523.     return Max(left,r.left) < Min(right,r.right)
  524.         && Max(top,r.top) < Min(bottom,r.bottom);
  525. }
  526.